
<template>
  1.
  <div>
    <!-- // 1.安装vue框架，进行删删改改 -->
  </div>
  2.token持久化
  <div>
    <!--        2.vuex - token持久化使用插件帮助我们自动把vuex的数据同步到本地进行持久化缓存
 2.1安装插件npm i vuex - persistedstate这个插件会保存到ls里不是cookie
 2.2创建目录 在store目录下，创建modules，里面2个vue文件，
 而文件不知道怎么写去官网查看，
 寻找vuex的生态vuex是组件的集中存储，每个 Vuex
 中心是store，由于 Vuex储是响应式的，因此从中“检索”状态的最简单方法是从计算属性中返回一些存储状态：
 2.3粘贴好后，把粘贴的导入他们的父页面上进行模块挂载,而子模块中要把命名空间开启
 2.4使用一开始安装的插件,不会的话,找文档里的插件
 2.4.1装好的包里面导入方法,执行导入方法,传来两个参数(key:本地储存，path：那个模块进行持久化操作 )
 2.5测试
 2.5.1在care.js文件进项测试===在stare里面写上数据,在mutations里面写个方法(方法里面satre),在进行
 开始修改stater.修改数据
 2.6在main.js里开始进行测试用，store.commit('模块名/修改的mutations里的方法')
/ 2.7让vuex还要在cookie存一份，百度搜索, -->
  </div>
  3.封装axios
  <div>
    <!-- 3.Axios封装处理
  3.1安装包npm i axios第三方包
  3.2新建 src/utils/request.js 模块
  3.3导入包/创建实例对象/拦截响应器和响应拦截去/封裝自动方法/导出封装自动方法

   -->
  </div>
  4.一级路由和二级路由
  <div>
    <!-- 4.1登入页
    src/views/login/index.vue，首页src/views/layout/index.vue为一级创建
    4.2在src/router/index.js进行导入配置
    4.3创建分类src/views/category/index.vue,在src/router/index.js进行导入配置
    配置到layout这个底下当他孩子,二级路由
     4.4二级路由导出口，不用创造组件和import导入，直接在temple上面写  <router-view />
     4.5创建home页一上来就可以看到的src/views/Home/index.vue，并且在src/router/index.js进行二级路由配置，path给他置空，可以作为默认的二级路由显示
     -->
  </div>
  5.less样式引入
  <div>
    <!-- 5.1新建文件 src/styles/common.less 在该文件写入常用的样式，在 main.js 导入
    src/styles/common.less -->
  </div>
  6.手动+自动less
  <div>
    <!-- 手动引入less方案
    6.1新建文件 src/styles/var.less
    6.2测试在app.vue里进行设置，先导入，
    自动引入less方案
    6.1安装vue add style-resources-loader，安装的时候会提示要不要继续，直接y，less
    6.2安装完毕后会在vue.config.js中自动添加配置 -->
  </div>
  7.布局页面
  <div>
    <!-- 布局页面
    7.1创建Layout/components/top-nav.vue头部导航,导入components里的index，注册组件
    7.2创建Layout/components/top-header.vue头部布局，导入components里的index，注册组件
    7.3Layout/compoennts/header-nav.vue分离出Layout/components/top-header.vue里面有个组件复用，导入到Layout/components/top-header.vue里面进行注册
    7.4Layout/components/layout-footer.vue底部布局，导入components里的index，注册组件
    7.5public/index.html 引入字体图标文件 -->
  </div>
  8.首页接口渲染
  <div>
    8.1创建api，api/home.js调接口发数据渲染页面(导入/utils/request下，接口封装函数)
    8.2去Layout/compoennts/header-nav.vue里写入封装函数在这里写铺数据，因为公用的
  </div>
  9.吸顶头部交互实现
  <div>
    <!-- 9.1如何让他固定，页面到多少显示固定，什么事件 监听滚动事件
    9.2创建src/components/header-sticky.vue，导入components里的index，注册组件
    9.3安装vue滚动方法 npm i @vueuse/core就是监听事件的，安装完之后导入，按照导入的事件填写
    9.4导入Layout/components/top-header.vue这个复件 -->
  </div>
  10.Home-vuex优化数据获取
  <div>
    <!-- 10.1.创建js文件放进home优化的，store/modules/categroy.js 10.
    2.categroy.js在这里面进行分化 -->
    <!-- vuex四个方法，state里给空数组，mutations里修改state里的数据要给2个参数（第一个传参是state，第二个是修改的）
         actions是异步执行，发送请求也是异步，在异步中传给mutations，要给个传参，调用api接口 -->
    <!-- 10.3删除header-nav.vue里面的发送数据，因为复用所以要把它删除
    10.4categroy.js里写的要导出对应的index里面
    10.5在layout/index里面导出调用categroy.js api接口 //
    10.5此处选中共同组件，做一次触发，减少 //
    10.5只想拿到store/modele/category里的异步函数在这里触发的话有一个dispath //
    10.5拿到store有一个方法可以调用
    10.6在header-nav.vue里导入vuex两个方法，computed计算属性是一个函数，useState是获取store固定的 -->
  </div>
  11Home- 分类和轮播图
  <div>
    <!-- 11.1先创建左侧home/components/home-category.vue，banner组件home/components/home-banner.vue，在home里index把这两个组件引入过去，挂载 -->
    <!-- 11.2开始渲染左侧数据，继续导入vuex里面的uesStore(拿到categroy.js里的store)，和conmputed（计算方法） -->
    <!-- 11.3在数据渲染的时候页面拥挤，只要前两个，因此要给他们拆开。方案
    // 方案1：
      // 直接在模板中做处理=== v-for="i in item.children.slice(0, 2)"
      // 方法2：
      // 不动模板，直接动数据
      return store.state.category.categoryList.map((item) => {
        return {
          id: item.id,
          name: item.name,
          children: item.children.slice(0, 2)
        }
      }) -->
    <!-- 11.4让鼠标移动左侧右边显示动态图 -->
    <!-- 11.5导入公共组件到main.js，进行注册 -->
    <!-- 11.6轮播图开始进行轮播 接口，铺 -->
  </div>
  12Home-骨架组件优化
  <div>
    <!-- 12.1准备两个 tempalte模板，一块用作骨架屏，一块真实的数据显示
    12.1找到一个判断条件，让同一时间内只有一个显示（有没有数据，或categoryList。length>0) -->
  </div>
  13新鲜好物+人气推荐
  <div>
    <!-- 13.1创建Home/components/home-panel.vue
    13.2在home里的index导入
    13.3接口铺数据 -->
  </div>
  14.图片懒加载
  <div>
    <!-- 在directiives文件里的index有详细 -->
  </div>
  15路由和组件
  <div>
    <!-- 15.1修改views/layout/header-nav.vue把a链接换成路由跳转
    15.2修改router/indexs.js在category后面添加id -->
  </div>
  16Banner区域实现
  <div>
    16.1把home-banner.vue里scripe的组件复制到category/index.js里，以及轮播图占位
    16.2发送请求,铺数据
  </div>
  17
  <div>
    <!--
      17.1创建商品信息区views/Good/index.vue
    17.2把封装的数据取路由链接上，可以跳转
    17.2封装接口，铺数据,在铺数据的时候有问题详情看views/Good/index.vue
    17.3图片预览信息，，铺数据（有公共代码）带入
    17.4商品规格sku 铺数据，
    17.5 数量购物车，准备封装一个公共用的组件，在src/components/Numbox/index.vue

    17.6在公共件进行一步一步装配
    步骤1：页面静态先搭建好
    步骤2：在script里面添加name属性，之后到公共组件里的index里面导入进去
    步骤3：公共完成之后到src/views/good.vue里面去占位（使用的是公共组件创建的名字）
    步骤4：先让购物车添加事件，以及value值响应到数据页面
    步骤5：在公共组件定义props针对++和--，在向good.vue里面给他传值，并且先给good.vue
    里面给他转换成数字，加上：，并且给他一个数据，让公共组件先进行判断，是否可以正常使用
    步骤6：针对购物车事件进行判断，在判断的时候，是要获取上面的props，因此在setup（传props这个参数），下面擦可以进行判断

    步骤7：给good.vue绑定v-model=“事件",声明，之后公共组件进行，prosp定义，若不定义，无法发生同步,并要把之前给公共组件的值，不能写死，而是写成good.vue里面的model，也在props声明

    步骤8：进行测试，给good.vue里面的v-moedel事件，传递一个计时器，会不会也能更改vuex里的数据，答案是不能的
    因此要在公共组件开始监听
    步骤9:在原始的7上面施行的第二个方案
    -->
  </div>
  19商品详细区+热榜区域
  <div>
    <!-- 19.1商品详细区 -->
    <!-- 步骤1：创建src/views/good/components/good-detail.vue里面写静态代码，以及把子组件传给父，导入以及注册名，子组件里的props是数据，一定要在父组件里需要写一下 -->
    <!-- 19.2热榜区域
    步骤1：创建src/views/good/components/good-detail.vue里面写静态代码，以及把子组件传给父，导入以及注册名
    步骤2： 调接口，铺数据
    步骤3：铺数据中遇到的问题。抬头标题哪里，一个复用组件，要用两次，标题和回来的type参数不一，解决如下
    1.在解决type这里，让父组件，在标签里确定type的number数字，==== <goodHotvue :type="1" />
    2.子组件接收父组件传来的type，用props接收，给他定义类型
    3.子组件在setup（传参）在铺数据的时候把type：调用props
    4.子组件写页面的时候，在标题用的插值表达式里放三元表达式，这个是固定的数字===<h3>{{ type === 1 ? "24小时" : "周" }}榜</h3>
    5.针对4的另一种方案值多的时候用《前端枚举》
     <h3>{{ TYPE[type] }}</h3>
        // 前端枚举
       const TYPE = {1: '24小时热榜',2: '周榜',3: '年榜'}-->
  </div>
  18登入页面
  <div>
    18.1
    <!-- 步骤1：创建登入页src/views/login/components/login-header.vue头部，login-footer.vue底部，login-form.vue表单
    步骤2：三个组件在父组件里面进行导入创建
    步骤3：安装校验插件是针对不用element组件，这个值针对表单npm i vee-validate@4.0.3

    步骤4：要导入和注册这个
    步骤5：定义表单的双向绑定数据,和校验规则,表单兜底校验
    -->
    <!-- 18.2账户登入实现
    步骤1:先要把用户登入的密码和对象保存token需要运用到vuex,把之前测试的数据删掉,现在用用登入
    步骤2:vuex里的user.js当做存放token登入页的token
    1.state声明一个对象
    2.mutations里注册一个对象(传参,(第一个参数上面的state),第二个参数(自定义一个参数是为了后面赋值给第一个参数),)
    3.actions里调接口,发请求,因此去api创建user.js,里面放接口,我这里调用接口
    4.这个接口里面需要传参数,因此,actions里面也需要传参数(ctx(这个是要的是mutations这个参数),{这个是接口需要的参数})
    5.调用actions修改数据ctx.commit('这个写mutations起的名字',res.result(这个是函数接口要的值语法糖拿出值))
    步骤3:login-form页面里,在判断兜底校验的时候,在里面把token取出来,触发actions实例对象
    先触发actions这个函数就要先导入useStore，在之后判断里面,调用store.dispath('模块名字/sctions起的名字',以及传递参数)
    此项目中这个是有两个参数的,还解构赋值呢，因此但是在这个项目，这里就不用写解构赋值,因为上面有定义一个常量，里面就有要传参的
    步骤4：把登入的token值放在请求拦截器里request.js里，取出vuex里的token，继续先导入useStore，之后导入出来，store.state.起的模块名字.state里给的数据名字.token
    步骤5 ：之后进行token判断，如果有有token{前面是请求头==后面是后端来告诉前端怎么拼}
    步骤6：去top-nav.vue里面登录状态适配，    template+v-if   如何判断条件登入就同token  状态适配两种方案
     方案1: <template v-if="$store.state.user.profile.token"></template>()
     方案2：setup(){1.在外面先拿到token值，之后导入
  //              2.这个token值不是死的，灵活的，因此用计算属性
                  3. retrun出去
                  4.定义的值到上面也许if判断去  }
  步骤6 有一容易错的点 获取vuex里的action异步函数，之后再跳转首页，这里在跳转的时候不是统一执行，而是先执行同步了，所以因此在调store发送的函数的时候，在前面加上await就可以都保持一致，一起跳转，
    -->
  </div>
  20退出登入
  <div>
    <!-- 1.先去user.js里面在mutations函数里做清空给他一个空值
    2.在top-nav里在退出这个按钮点击事件，调用vuex里的清空 3.之后跳到首页
    4.针对有的到了详情页，退出，但是他在要进入的时候依旧是进入详情页，这个步骤
    步骤1：先导入usestor
    步骤2：在上面第三条跳到首页的时候给他router（）里放入对象，
    把跳入登入页写在这个里面之后再给一个参数，
    参数里面定义个redirectUrl:encodeURIComponent(route.fullPath)
    这个也就是跳转的时候让他编译一下（里面的是既有路径也有参数）
    5.针对记录当前发生退出登录行为时完整地址 fullPath path +
    路径参数，之后让登入的时候也保持上次登入的未保留地址
    步骤1：在login-from里面先进行取到top-nav退出未完成的路径，用usestore（），，之后取出来
    步骤2：针对为完整的数据取出来之后进行判断
    ，如果判断条件有未完成整那么给他路由跳转的时候router.push(里面把他转义回来（这个是上面获取出来的参数）)
    否在else就直接让他跳转到登入页router.push({路径}) -->
  </div>
  21消息提示组件封装
  <div>
    看app.vue简单测试的，封装好的在components.index.index.js以及login-from.vue
  </div>
  22购物车
  <div>
    1.购物车添加点击事件，之后再点击事件进行判断有token的话就可以点击，无token，就给个提示，用封装组件
    2.在care.js里写上数据，修改数据，调用接口（接口创建一个user.js)
    3.在good/index.vue里吧care.js里的函数拿取过来，之后拿取过来有参数，对参数，按照当前文件，选取，之后进队对参数两个做一个判断
    两个勾选才可以加入购物车，若少一个那么就给信息提示 4
    src/Layout/components/header-cart.vue新建头部组件
    并把它放挂载到top-header.vue里
    4.header-cart.vue获取care.js里的列表，铺数据，v-for
    5.计算总件数和总钱数在care.getter里面计算属性，之后把计算的属性继续铺数据到页面.header-cart.vue
  </div>
  23 目标：购物车列表功能
  <div>
    1.新建购物车页面组件 src/views/cart/index.vue
    2.去router路由去挂载这个购物车页面组件，
    3.去header-cart去绑定跳转路由在去购物车结算中
    4.去cart/index.vue去那取到care.js里的数据(vux)，用useStore才可以拿取，之后渲染页面数据
    5.去care.js去计算把已选择全选框计算出来，先进行fitele过滤里面的每一项的selecetde为true的时候，，让count相加
    6.去cart/index.vue吧计算好的已选择的属性，用coumpted方法来写，因为要依赖不同变化，之后挂载到标签上的还有共多少件商品
    7.去care.js去计算把商品总合计的计算出来，先进行fitele过滤里面的每一项的selecetde为true的时候，，让count*价格
    8.去cart/index.vue吧计算好的商品总合计的计算，用coumpted方法来写，因为要依赖不同变化，之后挂载到标签上，
  </div>
  24当vuex遇到v-model为了修改全选勾选框（演示）
  <div>
    1.先去store/index.js定义严格模式开启strict:
    true,//但是会报错，因为不允许修改v-model数据
    2.在index.vue里在勾选状态，让父亲传个子，是为了把数据的勾选状态发给子
    3.在components/nembox/index.vue里子传父，把自定义事件方法传给父亲
    3.1在传给自定义事件的时候遇到了一些问题，子那边传来的点击事件，如何获取到当前的id，因为勾选已经传给子了
    解决办法，就是用固定公式，在标签上 @change="(selected) => checkChange(i,
    selected)"这是固定写法
    除了默认参，在补一个参数进来，绑回一个返回值，在里面selected作为默认参，在返回补一个参数i进去，和默认参也进去
    3.2在点击事件的时候，这样就可以把id也穿进去了。
    4.在定义一个commit事件，在触发点击事件的时候
    4.1在care.js里mutations创建一个修改勾选状态的方法
    里面传两个值（一个是要修改上面tate的数据，（一个是id，一个是勾选状态）这里面给他们大花括号，结构赋值的
    ）里面遍历数据每一项等于要查找的id，和勾选的状态
    4.2在index.vue组件在点击事件里，把自定义的时间commit（‘模块名/起的函数方法名称’{id和勾选状态===等于你在这里给的}）
  </div>
  25单选操作实现
  <div>
    1.调接口，依然防水vuex里（care.js），这个接口有三个参数，因此在要定义的时候把这三个参数顶一个对象，不用结构赋值，自己知道就好
    2.去vue，定义这个函数，在上面24的时候有测试过，把数据隐藏，在这里面写上，调用vuex（care.js）里的接口方法
    也要传递三个参数，但是在这里给他结构出来，因为在上面有那取到vuex里的数据，并且进行v-for，有值是i，在这里定义的
  </div>
  26全选
  <div>
    1.掉接口，到vuex里，里面有一个参数是商品的所有id，这个不用写进去，因为vuex里的state就有这个数据，但是在立马写的时候要映射这个
    2.在页面定义事件，在vue文件里点击方法，拿取vuex里的数据
    3.拿取完之后，但是要判断勾选小的大的也一起联动
    4.去vuex里的计算属性，声明一个方法，并且every每一项都满足，我要勾选的
    5.在vuex里标签上动态绑定声明的vuex计算的方法
  </div>
  27,修改（未做完）
  <div>
    1.引入之前封装好的插件components/Number/index.vue，针对数量，引入进来会有一个问题，显示数量框框（因为框框在购物车的时候是需要，而在我此时结算购物车页面时不需要的）
    2.针对这个数量，可以在封装组件中里的props，写上一个针对数量的对象，布尔值，并且让他默认是显示的
    3.并把这个针对数量的进行这个封装组件标签里，进行判断v-if=‘声明的变量’
    4.针对购物车组件，把这个针对数量的组件进行标签传父
    :数量的变量名=false（因为这里不需要显示）
    5.组件封装的时候本是可以写v-model双向绑定数值，但是呢，已经开始严格模式下了，因此就不能使用v-model会报错，
    所以我们用组件内的modelValue在父的标签身上绑定这个，值就是当前的数量
    6.想做加号和减号的时候要反向修改到vuex里面，在子组件里单独触发一个自定义事件让他双向绑入值
    并在如上面点击这个自定义绑定事件，在底下触发点击事件
  </div>
  28下单结算实现
  <div>
    1.先创建一个新的下单结算页面跳转views/settlement/index.vue
    2，去router声明这个跳转
    3.去cart/index页面里下单结算绑定点击事件，之后事件里判断商品计算已选择的value值等于等于0的话，给他一个提示信息提示是之前封装的组件message里，导入
  </div>
  29结算模块
  <div>
    1.结算页面views/settlement/index.vue这个md粘贴
    2.创建一个新的文件夹，放当前结算模块的接口,api/order.js
    这个3的问题我是没有遇到，
    3.接口写完，settlement/index.vue页面调用数据，渲染页面，但是渲染页面会遇到..的那这个就是可选链
    可选链：第一种方式？
    第二种方式v-if=判断（选择第二种，因为这样就不用一直写？？？？）
    针对3的问题：我的页面时这样写的，我在刚开始就v-for了，就没有给我报错..的问题
    4.地址
    4.1地址需要在setup声明一个地址把值给声明的，在接口里面地址有一个===isDefault=1就是默认地址，isDefault=0就是普通地址在，result.userAddresses里
    4.2接口声明的地址也是一个对象，要想拿到isDefault===1默认的，必须要查找一下,
    <!-- 4.3拿到之后要判断一下如：如果item没有找到那么就是undefind
      if (item) { //如果item存在的话，给他赋值
     address.value = item }
      else { //如果没有找到的话，就用第一项做值
     address.value = res.result.userAddresses[0]
    } -->
    4.4渲染页面 4.5页面里有一个
    您需要先添加收货地址才可提交订单。这个需要v-if一下，因为当收获地址长度为0
    的时候是真的没有这个地址，所以客户填写 4.6ul里面给他v-else
  </div>
  30.切换地址实现
  <div>
    1.绑定点击事件
    2.去公共组件Dialog/index.vue,公共组件props传来两个参数，一个字符串，一个弹框布尔，
    在父页面上进行第一步骤
    <XtxDialog title="切换收获地址" :visible="visible">
      <template #default>主体内容</template>
      <template #footer> 按钮</template>
    </XtxDialog>
    第二步骤
    切换地址点击事件，之后给visible在底下定义，之后点击事件进行修改visible下的定义的值
    第三步骤 去公共组件里面有一个关闭自定义事件，传给父这边
    <XtxDialog title="切换收获地址" :visible="visible" 自定义事件></XtxDialog>
    第四步骤 去底下声明安把值改成false 3.切换地址 md粘贴要复制
    <template #default>主体内容</template>
    <template #footer> 按钮</template>
    <!-- 并把粘贴的v-for的名称在修改一下 -->
    3.1样式也要粘贴一下，因为样式里面有一个active有他地址框会显示出来样式绿色的没有就不显示
    3.2页面 tab栏切换类交互的通用实现逻辑 思路:
    <!-- 1.点击是记录当前点击了谁(哪项的id)
    2.通过动态类名控制active显示:class='{active:条件}' 3.条件就是
    当前通过v-for遍历时当前的id是否等于我们记录下来的值===固定语法

      <div
            class="text item"
            v-for="item in checkoutInfo.userAddresses"
            :key="item.id"
            @click="switchAddresser(item)"思路1
            思路2+3
            :class="{ active: item.id === activation.id }"
            思路1绑定事件，要去底下声明一下，并且给一个对象，就是记录当前点的是那个id，为3条件记录下来的值
          > -->
    3.3把切换好的地址替换页面上的
    在确定的时候点击事件，之后让刚开始声明的放地址的的value值等于记录对象的value值，并且还要把弹框false关闭
  </div>
  31.提交订单
  <div>
    1.调接口 2.页面提交订单点击事件，把接口函数放在点击事件里面，调用接口有值
    <!-- await createOrder({//函数
    deliveryTimeType: 1,
    payType: 1,
     buyerMessage: '',
    addressId: address.value.id, // 地址id这个是在上面声明过 goods:
    checkoutInfo.value.goods.map(item =>{//声明声明过.goods（接口好物）“map()方法可以创建一个新数组,其结果是该数组中的每个元素都是调用一个提供的函数后返回的结果”
    return { skuId: item.skuId, count: item.count } } ) -->
  </div>
  32.支付模块
  <div>
    1.views/pay/index.vue针对支付页面的，md赋值 , 
    2.配置路由(路由需要穿带参数)
    3.提交事件里在外声明vuex里的路由跳转，之后把跳转写到这个事件里面===src/views/settlement.index.vue
    4.在刷新列表购物车，调接口，之前调过，直接复制，commit
    5.调接口获取订单详情接口
    6.之后详情铺数据
    
  </div>
  33.封装一个倒计时函数
  <div>
    1.创建一个文件夹compositions/usecountDown.js===具体步骤看这个文件
    2.pay/index.vue也有标*了可以直接看
  </div>
</template>
<script>

</script>
